#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# Copyright 2007 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import webapp2
import os
import jinja2
from google.appengine.ext import db
import numpy as np
import logging

templates_dir = os.path.join(os.path.dirname(__file__), 'templates')
env = jinja2.Environment(loader=jinja2.FileSystemLoader(templates_dir), autoescape=True)

def render_str(template, **params):
    t = env.get_template(template)
    return t.render(params)


class BaseHandler(webapp2.RequestHandler):
    def render(self, template, **kw):
        self.response.out.write(render_str(template, **kw))

    def write(self, *a, **kw):
        self.response.out.write(*a, **kw)


class AboutHandler(BaseHandler):
    def get(self):
        self.render('about.html')

class MainHandler(BaseHandler):
    def get(self):
        self.render('index.html')


tariffs = {"t1": u"Первый",
           "t2": u"Второй",
           "t3": u"Третий",
           "t4": u"Четвертый"
           }
criterions = {"c1": u"Цена",
              "c2": u"Интернет",
              "c3": u"Доступность",
              "c4": u"Реклама"
           }


class InputDatahandler(BaseHandler):
    def write_form(self, error=""):
        self.render('choise.html', tariffs_len=len(tariffs),
                                   tariffs=tariffs,
                                   criterions_len=len(criterions),
                                   criterions=criterions,
                                   error=error)

    def get(self):
        self.write_form()

    def post(self):
        self.redirect('/compare/')


class DelTariffHandler(BaseHandler):
    pass


class AddTariffHandler(BaseHandler):
    def write_form(self, error=""):
        self.render('choise.html', tariffs_len=len(tariffs),
                                   tariffs=tariffs,
                                   criterions_len=len(criterions),
                                   criterions=criterions,
                                   tariff_error=error)

    def get(self):
        self.write_form()

    def post(self):
        tariff_name = self.request.get('tariff_name')
        if tariff_name:
            ind = "t%d" % (len(tariffs)+1)
            tariffs[ind] = tariff_name
            self.write_form()
        else:
            self.write_form(error="Invalid tariff name!")


class DelCriterionHandler(BaseHandler):
    pass


class AddCriterionHandler(BaseHandler):
    def write_form(self, error=""):
        self.render('choise.html', tariffs_len=len(tariffs),
                                   tariffs=tariffs,
                                   criterions_len=len(criterions),
                                   criterions=criterions,
                                   criterion_error=error)

    def get(self):
        self.write_form()

    def post(self):
        criterion_name = self.request.get('criterion_name')
        if criterion_name:
            ind = "c%d" % (len(criterions)+1)
            criterions[ind] = criterion_name
            self.write_form()
        else:
            self.write_form(error="Invalid criterion name!")

texts_t = []
for criterion in criterions.values():
    for i in range(len(tariffs.values())-1):
        for j in range(i+1, len(tariffs.values())):
            texts_t.append(u'Сравниваем A: \"%s\" и B: \"%s\"\n\nпо критерию \"%s\"' % (tariffs.values()[i],
                                                                                tariffs.values()[j],
                                                                                criterion))
texts_c = []
for i in range(len(criterions.values())-1):
    for j in range(i+1, len(criterions.values())):
        texts_c.append(u'Сравниваем A: \"%s\" и B: \"%s\"' % (criterions.values()[i],
                                                              criterions.values()[j]))

global_tariffs_matrix = []
global_criterions_matrix = []

class CompareHandler(BaseHandler):
    def write_form(self, text, itemsList):
        self.render('compare.html', text=text, items_list=itemsList)

    def get(self):
        """Create widget for each pare of tariffs"""
        n = len(tariffs)

        itemsList = [u'A абсолютно превосходит B', u'A явно важнее В',
                     u'А значительно важнее B',    u'А незначительно важнее В',
                     u'A и В одинаково важны',     u'B незначительно важнее A',
                     u'B значительно важнее A',    u'B явно важнее A',
                     u'B абсолютно превосходит A']
        itemsPoints = [9, 7, 5, 3, 1, 1./3, 1./5, 1./7, 1./9]

        matrixIndex = 0

        # Compare every tariff
        if len(texts_t) != 0:
            self.write_form(texts_t.pop(), itemsList)
            it_i = self.request.get('item')
            item_ind = int(it_i) if it_i else -1
            if item_ind != -1:
                global_tariffs_matrix.append(itemsPoints[item_ind])
                self.redirect('/compare/')

        # Compare every criterion
        elif len(texts_c) != 0:
            self.write_form(texts_c.pop(), itemsList)
            it_i = self.request.get('item')
            item_ind = int(it_i) if it_i else -1
            if item_ind != -1:
                global_criterions_matrix.append(itemsPoints[item_ind])
                self.redirect('/compare/')
        else:
            # print global_tariffs_matrix
            # print global_criterions_matrix
            tariffs_matrix = self.get_real_matrix(global_tariffs_matrix, len(tariffs.values()))
            # Get normalized vector for tariffs matrix
            tariffs_vector = self.get_normalized_vector(tariffs_matrix)
            # The same thing for criterions
            criterions_matrix = self.get_real_matrix(global_criterions_matrix, len(criterions.values()))
            criterions_vector = self.get_normalized_vector(criterions_matrix)

            # print tariffs_vector
            # print criterions_vector
            self.redirect('/result/')

    def vector_sort(self, l1, l2):
        """l1 -собственные числа, а l2 - с.в"""
        for i in xrange(len(l1)-1):
            for j in xrange(len(l1)-1):
                if l1[j] < l1[j+1]:
                    b = l1[j+1]
                    l1[j+1] = l1[j]
                    l1[j] =  b
                    a = l2[j+1].copy()
                    l2[j+1] = l2[j]
                    l2[j] = a
        return l1, l2

    def get_real_matrix(self, bad_matrix, n):
        matrix = self.get_clean_matrix(n)
        for i in range(n-1):
            for j in range(i+1, n):
                if len(bad_matrix) == 0:
                  break
                val = bad_matrix.pop()
                matrix[i][j] = val
                matrix[j][i] = 1./val

        return matrix

    def get_clean_matrix(self, n):
      """Return clean matrix full of 0 and 1 on main diagonal"""
      matrix = []
      for i in range(n):
          m = []
          for j in range(n):
              if i == j:
                  m.append(1)
              else:
                  m.append(0)
          matrix.append(m)
      return matrix

    def get_normalized_vector(self, matrix):
        """Get magic vector"""
        a = np.mat(matrix)
        la, v = np.linalg.eig(a) # ищем в матрице собственные числа и \
                                 #собственные вектора
        la, v = self.vector_sort(la, v)
        c = v[0]

        d = c.A # преобразуем матрицу в массив
        n = len(d[0])
        s = 0
        for i in xrange(n):
            s += d[0,i] ** 2
        s = s ** 0.5

        g = []
        for i in xrange(n):
            g.append(d[0, i] / s)

        return g # нормированный вектор


class ResultHandler(BaseHandler):
    def write_form(self):
        self.render('result.html')

    def get(self):
        self.write_form()

app = webapp2.WSGIApplication([('/', MainHandler),
                               ('/about/', AboutHandler),
                               ('/choise/', InputDatahandler),
                               ('/choise/add_tariff', AddTariffHandler),
                               ('/choise/del_tariff', DelTariffHandler),
                               ('/choise/add_criterion', AddCriterionHandler),
                               ('/choise/del_criterion', DelCriterionHandler),
                               ('/compare/', CompareHandler),
                               ('/result/', ResultHandler)],
                              debug=True)
